#!/usr/bin/python

import os
import re
import fnmatch

UNRAR = '/Users/valankar/rar/unrar'
ACTIVE_TORRENT_DIR = '/Users/valankar/Library/Application Support/Azureus/active'

def CleanupTitle(title):
  return title.replace('.', ' ').title()

def GetTitle(path):
  # V.for.Vendetta.2005.iNTERNAL.DVDRip.XviD-UNDEAD
  found = re.compile(r'(.*).\d{4}.*').findall(path)
  if found:
    return CleanupTitle(found[0])
  found = re.compile(r'(.*?)\.(festival|dc|real|limited|proper|r5|dvdscr|dvdr)', re.IGNORECASE).findall(path)
  if found:
    return CleanupTitle(found[0][0])
  return None
  
def PruneRars(rars):
  """Only keep the first rar."""
  if rars and 'part' in rars[0]:
    return rars[0:1]
  return rars

def FindFirstRarsFromFilelist(filelist):
  """Matches .rar, .001, etc."""
  rars = [x for x in filelist if x.endswith('.rar')]
  if rars:
    return rars
  rars = [x for x in filelist if x.endswith('.001')]
  if rars:
    return rars
  return []

def GetRars(dir):
  filelist = os.listdir(dir)
  rars = PruneRars(FindFirstRarsFromFilelist(filelist))
  subdirs = [x for x in filelist if os.path.isdir(os.path.join(dir, x))]
  for subdir in subdirs:
    filelist = os.listdir(os.path.join(dir, subdir))
    rars.extend(PruneRars([os.path.join(subdir, x) for x in FindFirstRarsFromFilelist(filelist)]))
  return rars

def GetNfos(dir):
  return fnmatch.filter(os.listdir(dir), '*.[Nn][Ff][Oo]')

def IsActiveTorrent(dir):
  return not os.spawnlp(os.P_WAIT, 'grep', 'grep', '-qr', dir, ACTIVE_TORRENT_DIR)
    
def ProcessMovie(dir, title, prompt=True):
  """Should chdir to movie directory before calling this."""
  unrar_success = True
  movie_dir = os.getcwd()
  # Unrar from old dir into new
  if os.path.exists(title):
    print 'Path %s already exists, skipping extraction.' % (title,)
  else:
    # Do extraction
    if prompt:
      user_title = raw_input('New name for %s [%s] (n to skip):\n' % (dir, title))
      if user_title == 'n':
        return
      if user_title:
        title = user_title
    
    # Figure out which rar file to start with
    rars = GetRars(dir)
    print 'Rars: %s' % (rars,)
    
    # Make new dir and unrar into it
    os.mkdir(title)
    os.chdir(title)
    for rar in rars:
      retval = os.spawnlp(os.P_WAIT, UNRAR, UNRAR, 'x', os.path.join(movie_dir, dir, rar))
      unrar_success = unrar_success and not retval

    # Check for rars that exist in extracted dir (subtitles, etc)
    for rar in GetRars('.'):
      if not os.spawnlp(os.P_WAIT, UNRAR, UNRAR, 'x', rar):
        os.spawnlp(os.P_WAIT, 'rm', 'rm', '-f', rar)
        
    # Get back out to where we were
    os.chdir(movie_dir)

  # Make sure files exist in destination dir
  if not os.listdir(title):
    print 'Destination dir %s has no files, removing and moving on.' % (title,)
    os.rmdir(title)
    return

  # Check if any unrars failed
  if not unrar_success:
    print 'Some unrars failed. Removing destination dir %s and moving on.' % (title,)
    assert not title.startswith('/')
    os.spawnlp(os.P_WAIT, 'rm', 'rm', '-rf', title)
    return

  # Copy nfo files  
  for nfo in GetNfos(dir):
    dest = os.path.join(title, nfo)
    if not os.path.exists(dest):
      print 'Copying nfo %s' % (nfo,)
      os.spawnlp(os.P_WAIT, 'cp', 'cp', os.path.join(dir, nfo), dest)

  # Check if active torrent
  if IsActiveTorrent(dir):
    print 'Active torrent %s, skipping deletion.' % (dir,)
    return
  
  # Prompt to remove old dir
  if prompt:
    if raw_input('Remove %s? [y] ' % (dir,)):
      return

  print 'Removing %s' % (dir,)
  assert len(dir) > 5
  os.spawnlp(os.P_WAIT, 'rm', 'rm', '-rf', dir)
  
def UnrarMovies(path):
  os.chdir(path)
  dirlist = [x for x in os.listdir('.') if os.path.isdir(x)]
  dirlist = [x for x in dirlist if x.count('.') > 1]
  for dir in dirlist:
    title = GetTitle(dir)
    if not title:
      print 'Unknown: %s' % (dir,)
      continue
    ProcessMovie(dir, title, prompt=False)


if __name__ == '__main__':
  UnrarMovies('/Volumes/Drobo/Movies')
